# -*- coding: utf-8 -*-
"""
# 使用了 [matplotlib==3.7.4]，遵循其 [PSF] 许可证，原始代码来源：[https://matplotlib.org]
# 使用了 [numpy==1.24.4]，遵循其 [BSD-3-Clause] 许可证，原始代码来源：[https://www.numpy.org]
# 使用了 [openpyxl==3.1.2]，遵循其 [MIT] 许可证，原始代码来源：[https://openpyxl.readthedocs.io]
# 使用了 [pandas==2.0.3]，遵循其 [BSD 3-Clause License] 许可证，原始代码来源：[https://pandas.pydata.org]
# 使用了 [pypinyin==0.55.0]，遵循其 [MIT] 许可证，原始代码来源：[https://github.com/mozillazg/python-pinyin]
"""
import logging
import os
import re
import sys
import time
import datetime
from pathlib import Path
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from openpyxl.styles import Alignment, Border, Font, Side
from openpyxl.cell.rich_text import TextBlock,CellRichText
from openpyxl.cell.text import InlineFont
from openpyxl.utils import get_column_letter
from pypinyin import Style, pinyin
from functools import wraps
sys.path.append(r"/media/sq/F:/E_Python/B_Basics/about_ocr/")
import OCR_basic_functions

class Timer:
    """函数执行计时装饰器 (文档末尾添加'mute'可禁止输出)"""
    def __init__(self, func):
        self.func = func
        wraps(func)(self)
    def __call__(self, *args, **kwargs):
        if (doc := self.func.__doc__) and not doc.endswith("mute"):
            print(doc)
        start = time.perf_counter()
        result = self.func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        print(f"  Function '{self.func.__name__}' executed in {elapsed:.4f} seconds")
        return result
    
class Config:
    CALLER_DIR = Path(sys.argv[0]).parent.resolve() if sys.argv[0] else Path.cwd()
    RESULT_DIR = CALLER_DIR / "result"
    RESULT_DIR.mkdir(parents=True, exist_ok=True)
    BASE_FONT = Font(name="宋体", size=9)
    RED=InlineFont(color="FF0000",rFont="SimSun",sz=9)
    BLACK=InlineFont(color="000000",rFont="SimSun",sz=9)
    CENTER_ALIGN = Alignment(horizontal='center', vertical='center', wrap_text=True)
    THIN_BORDER = Border(
        left=Side(style='thin'),
        right=Side(style='thin'),
        top=Side(style='thin'),
        bottom=Side(style='thin')
    )
    PAT_CLEAN = re.compile(r'[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]')
    FIGURE_DPI = 300
    
def sort_chinese_pinyin(lst):
    return sorted(lst,key=lambda s: [p[0] for p in pinyin(s, style=Style.TONE3)])
    
def get_timestamped_filename(file_type: str, prefix: str = "") -> Path:
    timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
    script_name = Path(sys.argv[0]).stem
    prefix_part = f"{prefix}_" if prefix else ""
    return Config.RESULT_DIR / f"{prefix_part}{script_name}_{timestamp}.{file_type}"

def save_text(content: str, filename: str) -> Path:
    file_path = Config.RESULT_DIR / f"{filename}.txt"
    try:
        file_path.write_text(content,encoding='utf-8')
        print(f"文本已保存至: {file_path}")
        return file_path
    except OSError as e:
        print(f"保存文本失败: {e}")
        raise

def save_markdown(keywords: list, prefix: str = "") -> Path:
    file_path = get_timestamped_filename("md", prefix)
    header = f"# Keywords: ({len(keywords)})\n\n"
    content = "\n".join(keywords)
    try:
        file_path.write_text(header + content, encoding='utf-8')
        print(f"Markdown已保存至: {file_path}")
        return file_path
    except OSError as e:
        print(f"保存Markdown失败: {e}")
        raise
        
def save_dataframe(df: pd.DataFrame, prefix: str = "",highlight_column="",highlight_pattern="") -> Path:
    file_path = get_timestamped_filename("xlsx", prefix)
    try:
        with pd.ExcelWriter(file_path, engine='openpyxl') as writer:
            df.to_excel(writer, index=False, sheet_name='Data')
            worksheet = writer.sheets['Data']
            _apply_dataframe_styles(worksheet, df,highlight_column,highlight_pattern)
        print(f"Excel已保存至: {file_path}")
        return file_path
    except Exception as e:
        print(f"保存DataFrame失败: {e}")
        raise
        
def _split_by_matches(string, pattern):
    matches = list(re.finditer(pattern, string))
    if not matches:
        return [string]
    segments = []
    start_index = 0
    for match in matches:
        if match.start() > start_index:
            segments.append(string[start_index:match.start()])
        segments.append(match.group())
        start_index = match.end()
    if start_index < len(string):
        segments.append(string[start_index:])
    return segments 
def _apply_dataframe_styles(worksheet, df: pd.DataFrame,highlight_column="",highlight_pattern=""):
    worksheet.freeze_panes = 'A2'
    for row in worksheet.iter_rows(min_row=1, max_row=len(df)+1):
        worksheet.row_dimensions[row[0].row].height = 12
    col_widths = []
    for col in df.columns:
        col_str = str(col)
        title_len = len(col_str)
        if df[col].empty:
            content_len = 0
        else:
            content_len = df[col].astype(str).str.len().max()
        col_width = min(max(title_len, content_len) + 2, 50)
        col_widths.append(col_width)
    for i, width in enumerate(col_widths, 1):
        col_letter = get_column_letter(i)
        worksheet.column_dimensions[col_letter].width = width
    for row in worksheet.iter_rows():
        for cell in row:
            cell.border = Config.THIN_BORDER
            cell.font = Config.BASE_FONT
            cell.alignment = Config.CENTER_ALIGN
    for cell in worksheet[1]:
        cell.font = Font(bold=True, name="宋体", size=9)
    if len(highlight_column)>0:
        max_len=0
        for cell in worksheet[highlight_column]:
            if cell.value:
                lines=str(cell.value).splitlines()
                cell_max_len=max(len(line) for line in lines) if lines else 0
                max_len=max(max_len,cell_max_len)
                li_split=_split_by_matches(cell.value,highlight_pattern)
                red_string=CellRichText([TextBlock(Config.RED,i) if re.match(highlight_pattern,i) else TextBlock(Config.BLACK,i) for i in li_split])
                cell.value=red_string
                
def save_figure(fig: plt.Figure, prefix: str = "") -> Path:
    file_path = get_timestamped_filename("png", prefix)
    try:
        fig.savefig(file_path,dpi=Config.FIGURE_DPI,bbox_inches='tight')
        print(f"图表已保存至: {file_path}")
        return file_path
    except Exception as e:
        print(f"保存图表失败: {e}")
        raise
    
def print_header(df):
    li=df.columns.values.tolist();
    for index,value in enumerate(li):
        print("%d,%s"%(index,value),end="-")
    print("end")
    
def df_count(column):
    value_counts_sorted=column.value_counts(sort=True,ascending=False,dropna=False)
    print(value_counts_sorted)

def get_bat_ocr_files(path):
    root_dir = path
    files = os.listdir(root_dir)
    for i in range(0, len(files)):
        fp = os.path.join(root_dir, files[i])
        new_fp = fp + ".txt"
        file = OCR_basic_functions.get_captcha(fp)
        time.sleep(2)
#        file = re.sub(r'\[', u'', file)
#        file = re.sub(r'([0-9]{1,})', u'\\1,', file)  # 序号.
#        file = re.sub(r'([男女])', u',\\1,', file)  # 性别.
#        file = re.sub(r'(公司)', u'\\1,', file)  # 公司.
        with open(new_fp, "w", encoding='utf-8') as w:
            w.write(file)
            w.close()

def append_txt(path):
    root_dir=path
    files=os.listdir(root_dir)
    files=[x for x in files if(x.endswith("txt"))]
    files.sort(key=lambda x:(x.split('.')[0]))
    new_fp=get_timestamped_filename("txt", prefix="合并结果")
    for i in range(0,len(files)):
        fp=os.path.join(root_dir,files[i])#路径+文件名.
        with open(fp) as f:
            data=f.read()
            with open(new_fp, "a", encoding='utf-8') as w:
                w.write(data)
                w.close()
            f.close()
    return(new_fp)
    
def clear_txt(path):
    new_fp=get_timestamped_filename("txt", prefix="清理结果")
    with open(path) as f:
        str_=f.read()
        str_=str_.strip()
        str_=re.sub(r'</?.*?>','',str_)
        str_=re.sub(r'&nbsp;','',str_)
        str_=re.sub(r'\n+','\n',str_)
        str_=re.sub(r'\s+',' ',str_)
        with open(new_fp, "a", encoding='utf-8') as w:
            w.write(str_)
            w.close()
        f.close()

def start_log(prefix=""):
    fn=get_timestamped_filename("log", prefix)
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S',
        filename=fn
    )
    return logging

if __name__ == "__main__":
    file_path = r"/home/sq/图片"
    get_bat_ocr_files(file_path)
#    start_log()